/**
 * ESLint 规则
 * 
 * 具体每条规则可以在https://cn.eslint.org/docs/rules/ 查询
 *
 * @category 此规则属于哪种分类
 * @reason 为什么要开启（关闭）此规则
 * @fixable 支持自动修复
 */
module.exports = {
    rules: {
        /**
         * 禁止 for 循环出现方向错误的循环
         * @category Possible Errors
         */
        'for-direction': 'error',
        /**
         * getter 必须有返回值，并且禁止返回空
         * @category Possible Errors
         */
        'getter-return': [
            'error',
            {
                allowImplicit: false
            }
        ],
        /**
         * 禁止将 async 函数做为 new Promise 的回调函数
         * @category Possible Errors
         * @reason 出现这种情况时，一般不需要使用 new Promise 实现异步了
         */
        'no-async-promise-executor': 'error',
        /**
         * 禁止与负零进行比较
         * @category Possible Errors
         */
        'no-compare-neg-zero': 'error',
        /**
         * 禁止在测试表达式中使用赋值语句，除非这个赋值语句被括号包起来了
         * @category Possible Errors
         */
        'no-cond-assign': ['error', 'except-parens'],
        /**
         * 禁止将常量作为分支条件判断中的测试表达式，但允许作为循环条件判断中的测试表达式
         * @category Possible Errors
         */
        'no-constant-condition': [
            'error',
            {
                checkLoops: false
            }
        ],
        /**
         * 禁止在对象字面量中出现重复名称的键名
         * @category Possible Errors
         */
        'no-dupe-keys': 'error',
        /**
         * 禁止在 switch 语句中出现重复测试表达式的 case
         * @category Possible Errors
         */
        'no-duplicate-case': 'error',
        /**
         * 禁止出现空代码块，允许 catch 为空代码块
         * @category Possible Errors
         */
        'no-empty': [
            'error',
            {
                allowEmptyCatch: true
            }
        ],
        /**
         * 禁止在正则表达式中使用空的字符集 []
         * @category Possible Errors
         */
        'no-empty-character-class': 'error',
        /**
         * 禁止将 catch 的第一个参数 error 重新赋值
         * @category Possible Errors
         */
        'no-ex-assign': 'error',
        /**
         * 禁止不必要的布尔类型转换，比如 !! 或 Boolean
         * @category Possible Errors
         * @fixable
         */
        'no-extra-boolean-cast': 'error',
        /**
         * 禁止函数表达式中出现多余的括号
         * @category Possible Errors
         * @fixable
         */
        'no-extra-parens': ['error', 'functions'],
        /**
         * 禁止出现多余的分号
         * @category Possible Errors
         * @fixable
         */
        'no-extra-semi': 'error',
        /**
         * 禁止将一个函数声明重新赋值
         * @category Possible Errors
         */
        'no-func-assign': 'error',
        /**
         * 禁止在 if 代码块内出现函数声明
         * @category Possible Errors
         */
        'no-inner-declarations': ['error', 'both'],
        /**
         * 禁止在 RegExp 构造函数中出现非法的正则表达式
         * @category Possible Errors
         */
        'no-invalid-regexp': 'error',
        /**
         * 禁止使用特殊空白符（比如全角空格），除非是出现在字符串、正则表达式或模版字符串中
         * @category Possible Errors
         */
        'no-irregular-whitespace': [
            'error',
            {
                skipStrings: true,
                skipComments: false,
                skipRegExps: true,
                skipTemplates: true
            }
        ],
        /**
         * 禁止正则表达式中使用肉眼无法区分的特殊字符
         * @category Possible Errors
         * @reason 某些特殊字符很难看出差异，最好不要在正则中使用
         */
        'no-misleading-character-class': 'error',
        /**
         * 禁止将 Math, JSON 或 Reflect 直接作为函数调用
         * @category Possible Errors
         */
        'no-obj-calls': 'error',
        /**
         * 禁止在正则表达式中出现连续的空格，必须使用 /foo {3}bar/ 代替
         * @category Possible Errors
         * @fixable
         */
        'no-regex-spaces': 'error',
        /**
         * 禁止在数组中出现连续的逗号
         * @category Possible Errors
         */
        'no-sparse-arrays': 'error',
        /**
         * 禁止在普通字符串中出现模版字符串里的变量形式
         * @category Possible Errors
         */
        'no-template-curly-in-string': 'error',
        /**
         * 禁止出现容易出错的多行表达式
         * @category Possible Errors
         */
        'no-unexpected-multiline': 'error',
        /**
         * 禁止在 return, throw, break 或 continue 之后还有代码
         * @category Possible Errors
         */
        'no-unreachable': 'error',
        /**
         * 禁止在 finally 中出现 return, throw, break 或 continue
         * @category Possible Errors
         */
        'no-unsafe-finally': 'error',
        /**
         * 禁止将 await 或 yield 的结果做为运算符的后面项
         * @category Possible Errors
         * @reason 这样会导致不符合预期的结果
         */
        'require-atomic-updates': 'error',
        /**
         * 必须使用 isNaN(foo) 而不是 foo === NaN
         * @category Possible Errors
         */
        'use-isnan': 'error',
        /**
         * typeof 表达式比较的对象必须是 'undefined', 'object', 'boolean', 'number', 'string', 'function' 或 'symbol'
         * @category Possible Errors
         */
        'valid-typeof': 'error',
        /**
         * setter 必须有对应的 getter，getter 可以没有对应的 setter
         * @category Best Practices
         */
        'accessor-pairs': [
            'error',
            {
                setWithoutGet: true,
                getWithoutSet: false
            }
        ],
        /**
         * 数组的方法除了 forEach 之外，回调函数必须有返回值
         * @category Best Practices
         */
        'array-callback-return': 'error',
        /**
         * 将 var 定义的变量视为块作用域，禁止在块外使用
         * @category Best Practices
         */
        'block-scoped-var': 'error',
        /**
         * 禁止函数的循环复杂度超过 20
         * @category Best Practices
         * @reason https://en.wikipedia.org/wiki/Cyclomatic_complexity
         */
        complexity: [
            'error',
            {
                max: 20
            }
        ],
        /**
         * if 后面必须要有 {，除非是单行 if
         * @category Best Practices
         * @fixable
         */
        curly: ['error', 'multi-line', 'consistent'],
        /**
         * 链式调用的时候，点号必须放在第二行开头处，禁止放在第一行结尾处
         * @category Best Practices
         * @fixable
         */
        'dot-location': ['error', 'property'],
        /**
         * 必须使用 === 或 !==，禁止使用 == 或 !=，与 null 比较时除外
         * @category Best Practices
         * @fixable
         */
        eqeqeq: [
            'error',
            'always',
            {
                null: 'ignore'
            }
        ],
        /**
         * for in 内部必须有 hasOwnProperty
         * @category Best Practices
         */
        'guard-for-in': 'error',
        /**
         * 禁止使用 caller 或 callee
         * @category Best Practices
         */
        'no-caller': 'error',
        /**
         * switch 的 case 内有变量定义的时候，必须使用大括号将 case 内变成一个代码块
         * @category Best Practices
         */
        'no-case-declarations': 'error',
        /**
         * 禁止使用 eval
         * @category Best Practices
         */
        'no-eval': 'error',
        /**
         * 禁止修改原生对象
         * @category Best Practices
         */
        'no-extend-native': 'error',
        /**
         * 禁止出现没必要的 bind
         * @category Best Practices
         * @fixable
         */
        'no-extra-bind': 'error',
        /**
         * 禁止出现没必要的 label
         * @category Best Practices
         * @fixable
         */
        'no-extra-label': 'error',
        /**
         * switch 的 case 内必须有 break, return 或 throw
         * @category Best Practices
         */
        'no-fallthrough': 'error',
        /**
         * 表示小数时，禁止省略 0，比如 .5
         * @category Best Practices
         * @fixable
         */
        'no-floating-decimal': 'error',
        /**
         * 禁止使用 !! ~ 等难以理解的运算符，仅允许使用 !!
         * @category Best Practices
         * @fixable
         */
        'no-implicit-coercion': [
            'error',
            {
                allow: ['!!']
            }
        ],
        /**
         * 禁止在 setTimeout 或 setInterval 中传入字符串，如 setTimeout('alert("Hi!")', 100);
         * @category Best Practices
         */
        'no-implied-eval': 'error',
        /**
         * 禁止使用 __iterator__
         * @category Best Practices
         */
        'no-iterator': 'error',
        /**
         * 禁止使用 label
         * @category Best Practices
         */
        'no-labels': 'error',
        /**
         * 禁止使用没必要的 {} 作为代码块
         * @category Best Practices
         */
        'no-lone-blocks': 'error',
        /**
         * 禁止在循环内的函数中出现循环体条件语句中定义的变量
         * @category Best Practices
         */
        'no-loop-func': 'error',
        /**
         * 禁止出现连续的多个空格，除非是注释前，或对齐对象的属性、变量定义、导入等
         * @category Best Practices
         * @fixable
         */
        'no-multi-spaces': [
            'error',
            {
                ignoreEOLComments: true,
                exceptions: {
                    Property: true,
                    BinaryExpression: false,
                    VariableDeclarator: true,
                    ImportDeclaration: true
                }
            }
        ],
        /**
         * 禁止使用 \ 来换行字符串
         * @category Best Practices
         */
        'no-multi-str': 'error',
        /**
         * 禁止直接 new 一个类而不赋值
         * @category Best Practices
         */
        'no-new': 'error',
        /**
         * 禁止使用 new Function，比如 let x = new Function("a", "b", "return a + b");
         * @category Best Practices
         */
        'no-new-func': 'error',
        /**
         * 禁止使用 new 来生成 String, Number 或 Boolean
         * @category Best Practices
         */
        'no-new-wrappers': 'error',
        /**
         * 禁止使用 0 开头的数字表示八进制数
         * @category Best Practices
         */
        'no-octal': 'error',
        /**
         * 禁止使用八进制的转义符
         * @category Best Practices
         */
        'no-octal-escape': 'error',
        /**
         * 禁止对函数的参数重新赋值
         * @category Best Practices
         */
        'no-param-reassign': 'error',
        /**
         * 禁止使用 __proto__
         * @category Best Practices
         */
        'no-proto': 'error',
        /**
         * 禁止重复定义变量
         * @category Best Practices
         */
        'no-redeclare': 'error',
        /**
         * 禁止在 return 语句里赋值
         * @category Best Practices
         */
        'no-return-assign': ['error', 'always'],
        /**
         * 禁止在 return 语句里使用 await
         * @category Best Practices
         */
        'no-return-await': 'error',
        /**
         * 禁止将自己赋值给自己
         * @category Best Practices
         */
        'no-self-assign': 'error',
        /**
         * 禁止将自己与自己比较
         * @category Best Practices
         */
        'no-self-compare': 'error',
        /**
         * 禁止使用逗号操作符
         * @category Best Practices
         */
        'no-sequences': 'error',
        /**
         * 禁止 throw 字面量，必须 throw 一个 Error 对象
         * @category Best Practices
         */
        'no-throw-literal': 'error',
        /**
         * 循环内必须对循环条件的变量有修改
         * @category Best Practices
         */
        'no-unmodified-loop-condition': 'error',
        /**
         * 禁止无用的表达式
         * @category Best Practices
         */
        'no-unused-expressions': [
            'error',
            {
                allowShortCircuit: true,
                allowTernary: true,
                allowTaggedTemplates: true
            }
        ],
        /**
         * 禁止出现没用的 label
         * @category Best Practices
         * @fixable
         */
        'no-unused-labels': 'error',
        /**
         * 禁止出现没必要的 call 或 apply
         * @category Best Practices
         */
        'no-useless-call': 'error',
        /**
         * 禁止在 catch 中仅仅只是把错误 throw 出去
         * @category Best Practices
         * @reason 这样的 catch 是没有意义的，等价于直接执行 try 里的代码
         */
        'no-useless-catch': 'error',
        /**
         * 禁止出现没必要的字符串连接
         * @category Best Practices
         */
        'no-useless-concat': 'error',
        /**
         * 禁止使用 void
         * @category Best Practices
         */
        'no-void': 'error',
        /**
         * 禁止使用 with
         * @category Best Practices
         */
        'no-with': 'error',
        /**
         * Promise 的 reject 中必须传入 Error 对象，而不是字面量
         * @category Best Practices
         */
        'prefer-promise-reject-errors': 'error',
        /**
         * parseInt 必须传入第二个参数
         * @category Best Practices
         */
        radix: 'error',
        /**
         * 立即执行的函数必须符合如下格式 (function () { alert('Hello') })()
         * @category Best Practices
         * @fixable
         */
        'wrap-iife': [
            'error',
            'inside',
            {
                functionPrototypeMethods: true
            }
        ],
        /**
         * 必须使用 if (foo === 5) 而不是 if (5 === foo)
         * @category Best Practices
         * @fixable
         */
        yoda: [
            'error',
            'never',
            {
                onlyEquality: true
            }
        ],
        /**
         * 禁止使用 'strict';
         * @category Strict Mode
         * @fixable
         */
        strict: ['error', 'never'],
        /**
         * 禁止 label 名称与定义过的变量重复
         * @category Variables
         */
        'no-label-var': 'error',
        /**
         * 禁止使用保留字作为变量名
         * @category Variables
         */
        'no-shadow-restricted-names': 'error',
        /**
         * 禁止使用未定义的变量
         * @category Variables
         */
        'no-undef': [
            'error',
            {
                typeof: false
            }
        ],
        /**
         * 禁止将 undefined 赋值给变量
         * @category Variables
         * @fixable
         */
        'no-undef-init': 'error',
        /**
         * 定义过的变量必须使用
         * @category Variables
         */
        'no-unused-vars': [
            'error',
            {
                vars: 'all',
                args: 'none',
                caughtErrors: 'none',
                ignoreRestSiblings: true
            }
        ],
        /**
         * 变量必须先定义后使用
         * @category Variables
         */
        'no-use-before-define': [
            'error',
            {
                functions: false,
                classes: false,
                variables: false
            }
        ],
       
        /**
         * 数组的括号内的前后禁止有空格
         * @category Stylistic Issues
         * @fixable
         */
        'array-bracket-spacing': ['error', 'never'],
        /**
         * 代码块如果在一行内，那么大括号内的首尾必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'block-spacing': ['error', 'always'],
        /**
         * 逗号前禁止有空格，逗号后必须要有空格
         * @category Stylistic Issues
         * @fixable
         */
        'comma-spacing': [
            'error',
            {
                before: false,
                after: true
            }
        ],
        /**
         * 禁止在行首写逗号
         * @category Stylistic Issues
         * @fixable
         */
        'comma-style': ['error', 'last'],
        /**
         * 用作对象的计算属性时，中括号内的首尾禁止有空格
         * @category Stylistic Issues
         * @fixable
         */
        'computed-property-spacing': ['error', 'never'],
        /**
         * 函数名和执行它的括号之间禁止有空格
         * @category Stylistic Issues
         * @fixable
         */
        'func-call-spacing': ['error', 'never'],
        /**
         * 函数赋值给变量的时候，函数名必须与变量名一致
         * @category Stylistic Issues
         */
        'func-name-matching': [
            'error',
            'always',
            {
                includeCommonJSModuleExports: false
            }
        ],
        /**
         * 函数参数要么同在一行要么每行一个
         * @category Stylistic Issues
         * @fixable
         */
        'function-paren-newline': ['error', 'multiline'],
        /**
         * jsx 中的属性必须用双引号
         * @category Stylistic Issues
         * @fixable
         */
        'jsx-quotes': ['error', 'prefer-double'],
        /**
         * 对象字面量中冒号前面禁止有空格，后面必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'key-spacing': [
            'error',
            {
                beforeColon: false,
                afterColon: true,
                mode: 'strict'
            }
        ],
        /**
         * 关键字前后必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'keyword-spacing': [
            'error',
            {
                before: true,
                after: true
            }
        ],
        /**
         * 代码块嵌套的深度禁止超过 5 层
         * @category Stylistic Issues
         */
        'max-depth': ['error', 5],
        /**
         * 回调函数嵌套禁止超过 3 层，多了请用 async await 替代
         * @category Stylistic Issues
         */
        'max-nested-callbacks': ['error', 3],
        /**
         * 函数的参数禁止超过 7 个
         * @category Stylistic Issues
         */
        'max-params': ['error', 7],
        /**
         * new 后面的类名必须首字母大写
         * @category Stylistic Issues
         */
        'new-cap': [
            'error',
            {
                newIsCap: true,
                capIsNew: false,
                properties: true
            }
        ],
        /**
         * new 后面的类必须有小括号
         * @category Stylistic Issues
         * @fixable
         */
        'new-parens': 'error',
        /**
         * 禁止使用 Array 构造函数
         * @category Stylistic Issues
         */
        'no-array-constructor': 'error',
        
        /**
         * 禁止混用空格和缩进
         * @category Stylistic Issues
         */
        'no-mixed-spaces-and-tabs': 'error',
        /**
         * 禁止出现超过三行的连续空行
         * @category Stylistic Issues
         * @fixable
         */
        'no-multiple-empty-lines': [
            'error',
            {
                max: 3,
                maxEOF: 1,
                maxBOF: 1
            }
        ],
        /**
         * 禁止直接 new Object
         * @category Stylistic Issues
         */
        'no-new-object': 'error',
        /**
         * 禁止行尾有空格
         * @category Stylistic Issues
         * @fixable
         */
        'no-trailing-spaces': 'error',
        /**
         * 禁止属性前有空格，比如 foo. bar()
         * @category Stylistic Issues
         * @fixable
         */
        'no-whitespace-before-property': 'error',
        /**
         * 禁止 if 后面不加大括号而写两行代码
         * @category Stylistic Issues
         * @fixable
         */
        'nonblock-statement-body-position': [
            'error',
            'beside',
            {
                overrides: {
                    while: 'below'
                }
            }
        ],
        /**
         * 大括号内的首尾必须有换行
         * @category Stylistic Issues
         * @fixable
         */
        'object-curly-newline': [
            'error',
            {
                multiline: true,
                consistent: true
            }
        ],
        /**
         * 对象字面量只有一行时，大括号内的首尾必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'object-curly-spacing': [
            'error',
            'always',
            {
                arraysInObjects: true,
                objectsInObjects: false
            }
        ],
        /**
         * 必须使用单引号，禁止使用双引号
         * @category Stylistic Issues
         * @fixable
         */
        quotes: [
            'error',
            'single',
            {
                avoidEscape: true,
                allowTemplateLiterals: true
            }
        ],
        /**
         * 结尾必须有分号
         * @category Stylistic Issues
         * @fixable
         */
        semi: [
            'error',
            'always',
            {
                omitLastInOneLineBlock: true
            }
        ],
        /**
         * 一行有多个语句时，分号前面禁止有空格，分号后面必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'semi-spacing': [
            'error',
            {
                before: false,
                after: true
            }
        ],
        /**
         * 分号必须写在行尾，禁止在行首出现
         * @category Stylistic Issues
         * @fixable
         */
        'semi-style': ['error', 'last'],
        /**
         * if, function 等的大括号之前必须要有空格，比如 if (a) {
         * @category Stylistic Issues
         * @fixable
         */
        'space-before-blocks': ['error', 'always'],
        /**
         * 命名函数表达式括号前禁止有空格，箭头函数表达式括号前面必须有一个空格
         * @category Stylistic Issues
         * @fixable
         */
        'space-before-function-paren': [
            'error',
            {
                anonymous: 'ignore',
                named: 'never',
                asyncArrow: 'always'
            }
        ],
        /**
         * 小括号内的首尾禁止有空格
         * @category Stylistic Issues
         * @fixable
         */
        'space-in-parens': ['error', 'never'],
        /**
         * 操作符左右必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'space-infix-ops': 'error',
        /**
         * new, typeof 等后面必须有空格，++, -- 等禁止有空格
         * @category Stylistic Issues
         * @fixable
         */
        'space-unary-ops': [
            'error',
            {
                words: true,
                nonwords: false
            }
        ],
        /**
         * 注释的斜线或 * 后必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'spaced-comment': [
            'error',
            'always',
            {
                block: {
                    exceptions: ['*'],
                    balanced: true
                }
            }
        ],
        /**
         * case 的冒号前禁止有空格，冒号后必须有空格
         * @category Stylistic Issues
         * @fixable
         */
        'switch-colon-spacing': [
            'error',
            {
                after: true,
                before: false
            }
        ],
        /**
         * 模版字符串的 tag 之后禁止有空格，比如 tag`Hello World`
         * @category Stylistic Issues
         * @fixable
         */
        'template-tag-spacing': ['error', 'never'],
        /**
         * 文件开头禁止有 BOM
         * @category Stylistic Issues
         * @fixable
         */
        'unicode-bom': ['error', 'never'],
        /**
         * 箭头函数的箭头前后必须有空格
         * @category ECMAScript 6
         * @fixable
         */
        'arrow-spacing': [
            'error',
            {
                before: true,
                after: true
            }
        ],
        /**
         * constructor 中必须有 super
         * @category ECMAScript 6
         */
        'constructor-super': 'error',
        /**
         * generator 的 * 前面禁止有空格，后面必须有空格
         * @category ECMAScript 6
         * @fixable
         */
        'generator-star-spacing': [
            'error',
            {
                before: false,
                after: true
            }
        ],
        /**
         * 禁止对定义过的 class 重新赋值
         * @category ECMAScript 6
         */
        'no-class-assign': 'error',
        /**
         * 禁止出现难以理解的箭头函数，比如 let x = a => 1 ? 2 : 3
         * @category ECMAScript 6
         * @fixable
         */
        'no-confusing-arrow': [
            'error',
            {
                allowParens: true
            }
        ],
        /**
         * 禁止对使用 const 定义的常量重新赋值
         * @category ECMAScript 6
         */
        'no-const-assign': 'error',
        /**
         * 禁止重复定义类
         * @category ECMAScript 6
         */
        'no-dupe-class-members': 'error',
        /**
         * 禁止重复导入模块
         * @category ECMAScript 6
         */
        'no-duplicate-imports': 'error',
        /**
         * 禁止使用 new 来生成 Symbol
         * @category ECMAScript 6
         */
        'no-new-symbol': 'error',
        /**
         * 禁止在 super 被调用之前使用 this 或 super
         * @category ECMAScript 6
         */
        'no-this-before-super': 'error',
        /**
         * 禁止出现没必要的计算键名，比如 let a = { ['0']: 0 };
         * @category ECMAScript 6
         * @fixable
         */
        'no-useless-computed-key': 'error',
        /**
         * 禁止出现没必要的 constructor，比如 constructor(value) { super(value) }
         * @category ECMAScript 6
         */
        'no-useless-constructor': 'error',
        /**
         * 禁止解构时出现同样名字的的重命名，比如 let { foo: foo } = bar;
         * @category ECMAScript 6
         * @fixable
         */
        'no-useless-rename': 'error',
        /**
         * generator 函数内必须有 yield
         * @category ECMAScript 6
         */
        'require-yield': 'error',
        /**
         * ... 的后面禁止有空格
         * @category ECMAScript 6
         * @fixable
         */
        'rest-spread-spacing': ['error', 'never'],
        /**
         * 创建 Symbol 时必须传入参数
         * @category ECMAScript 6
         */
        'symbol-description': 'error',
        /**
         * ${name} 内的首尾禁止有空格
         * @category ECMAScript 6
         * @fixable
         */
        'template-curly-spacing': ['error', 'never'],
        /**
         * yield* 后面必须要有空格
         * @category ECMAScript 6
         * @fixable
         */
        'yield-star-spacing': ['error', 'after']
    }
};

